package com.study.util.treeutil;

import java.util.ArrayList;
import java.util.List;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import cn.hutool.core.util.ReflectUtil;

/**
 * 要满足上述需求，简单做法就将remark属性直接添加到 TreeNode 类中，Convert中赋下值，这不就满足了，但想想又不对，今天这个前端伙计缺个remark，明天可能别的伙计又缺个其他属性，全加到TreeNode中，TreeNode到底是树节点还是业务实体，所以不能这么搞。
 * 这里要处理成可扩展，同时满足开闭原则，所以此处比较妥的处理方式是继承，TreeNode属性满足不了的情况下，通过继承扩展具体业务的树节点来实现。
 */
/**
 * 树构建
 * 
 * @author chenk
 *
 */
public class TreeUtil_3_0 {

	/**
	 * 新增的属性转换方法
	 * 
	 * @author chenk
	 *
	 * @param <T>
	 * @param <TreeNode>
	 */
	public interface Convert<T, TreeNode> {
		public void convert(T t, TreeNode treeNode);
	}

	/**
	 * 树构建
	 * 
	 * @param <T>
	 * 
	 * @param <T>
	 * @param menuEntityList
	 * @param parentId
	 * @param convert
	 * @return
	 */
	public static <T, E extends TreeNode> List<E> build(List<T> list, Object parentId, Class<E> treeNodeClass,
			Convert<T, E> convert) {

		// 原来调用方法做的事情
		List<E> treeNodes = new ArrayList<>();
		for (T obj : list) {
			E treeNode = ReflectUtil.newInstance(treeNodeClass);
			convert.convert(obj, treeNode);
			treeNodes.add(treeNode);
		}

		List<E> finalTreeNodes = new ArrayList<>();
		for (E treeNode : treeNodes) {
			if (parentId.equals(treeNode.getParentId())) {
				finalTreeNodes.add(treeNode);
				innerBuild(treeNodes, treeNode);
			}
		}

		return finalTreeNodes;

	}

	private static <E> void innerBuild(List<E> treeNodes, E parentNode) {
		TreeNode t = (com.study.util.treeutil.TreeNode) parentNode;
		for (E e : treeNodes) {
			TreeNode childNode = (com.study.util.treeutil.TreeNode) e;
			if (t.getId().equals(childNode.getParentId())) {
				List<TreeNode> children = t.getChildren();
				if (children == null) {
					children = new ArrayList<>();
					t.setChildren(children);
					childNode.setParentId(t.getId());
				}
				children.add(childNode);
				childNode.setParentId(t.getId());
				innerBuild(treeNodes, e);
			}
		}
	}

	public static void main(String[] args) throws JsonProcessingException {
		// 1.模拟菜单数据
		List<MenuEntity> list = new ArrayList<>();
		list.add(new MenuEntity("1", "0", "系统管理", "sys", "/sys"));
		list.add(new MenuEntity("11", "1", "用户管理", "user", "/sys/user"));
		list.add(new MenuEntity("111", "11", "用户添加", "userAdd", "/sys/user/add"));
		list.add(new MenuEntity("2", "0", "店铺管理", "store", "/store"));
		list.add(new MenuEntity("21", "2", "商品管理", "shop", "/shop"));

		// 2.MenuEntity->TreeNode
		List<MenuEntityTreeNode> treeNodes = TreeUtil_3_0.build(list, "0", MenuEntityTreeNode.class,
				new Convert<MenuEntity, MenuEntityTreeNode>() {

					@Override
					public void convert(MenuEntity menuEntity, MenuEntityTreeNode treeNode) {
						treeNode.setId(menuEntity.getId());
						treeNode.setParentId(menuEntity.getPid());
						treeNode.setCode(menuEntity.getCode());
						treeNode.setName(menuEntity.getName());
						treeNode.setLinkUrl(menuEntity.getUrl());

						//
						treeNode.setRemark("备注111");
					}
				});

		// 3.返回
		ObjectMapper om = new ObjectMapper();
		String result = om.writeValueAsString(treeNodes);
		System.out.println(result);
	}
}
